/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package memoriavirtual;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;

/**
 *
 * @author Raissa2
 */
public class MemoriaVirtualController {

    private JanelaPrincipal view;
    private MemoriaVirtual model;
    public int momentoAtual = 0;
    public int ponteiroMS = 0;

    public MemoriaVirtualController(MemoriaVirtual model, JanelaPrincipal view) {
        this.model = model;
        this.view = view;
    }

    public void configurar(int tamMS, int tamMP, int tamQuadro, int tamEndLogico, ArrayList<Processo> processos, String politica, String escopo) {
        this.model = new MemoriaVirtual(tamMS, tamMP, tamQuadro, tamEndLogico, processos, politica, escopo);
        carregaProcessosMS(processos);
    }

    public void carregaMP() {
        view.MemoriaPrincipalModel = model.getMemoriaPrincipal().getMP();
        view.jTable_MemoriaPrincipal.setModel(view.MemoriaPrincipalModel);
    }

    public void carregaMS() {
        view.MemoriaSecundariaModel = this.model.getMemoriaSecundaria().getMS();
        view.jTable_MemoriaSecundaria.setModel(view.MemoriaSecundariaModel);
    }

    public DefaultTableModel getTP(String nome) {
        TP tabelaPagina = (TP) model.getMemoriaPrincipal().getProcessos_TP().get(nome);
        return tabelaPagina.getTPModel();
    }

    public boolean isTPCarregada(String nome) {
        TP tabelaPagina = (TP) model.getMemoriaPrincipal().getProcessos_TP().get(nome);
        return tabelaPagina == null;
    }

//    public void carregaProcessosMS(ArrayList<Processo> processos) {
//        HashMap<String, TP> hashTPs = this.model.getMemoriaPrincipal().getProcessos_TP();
//        MemoriaSecundaria ms = this.model.getMemoriaSecundaria();
//        Iterator itr = processos.iterator();
//        Processo processo;
//        int anterior = 0;
//        Pagina pagina;
//        while (itr.hasNext()) {
//            processo = (Processo) itr.next();
//
//            System.out.println(processo.getNome());
//
//            for (int i = anterior; i < anterior + processo.getPaginas().length; i++) {
//                pagina = new Pagina(-1, processo.getNome(), processo.getTamanhoImg(), -1, -1, true);
//                ms.setQuadro(new Quadro(pagina), i);
//                hashTPs.get(processo.getNome()).
//                        getCelulas()[i - anterior].setCelulaTP(i - anterior, false, false, i);
//            }
//            anterior = anterior + processo.getPaginas().length;
//        }
//    }
    public void carregaProcessosMS(ArrayList<Processo> processos) {
        MemoriaSecundaria ms = this.model.getMemoriaSecundaria();
        Pagina pagina;
        int anterior = 0;
        for (int i = 0; i < processos.size(); i++) {
            for (int j = 0; j < processos.get(i).getPaginas().length; j++) {
                pagina = new Pagina(-1, processos.get(i).getNome(), processos.get(i).getTamanhoImg(), -1, -1, true);
                ms.setQuadro(new Quadro(pagina), anterior);
                anterior++;
            }
        }
    }

    public void leInstrucao(String[] parametros, ArrayList<Processo> processos, int tamEndLogico) {
        executaInstrucao2(parametros[0], parametros[1].charAt(0), parametros[2], processos);
    }

    public void executaInstrucao(String nomeProc, char tipoInstrucao, String enderecoLogico, ArrayList<Processo> processos) {
        System.out.println("nome do processo " + nomeProc);
        System.out.println("tipo instrucao" + tipoInstrucao);
        System.out.println("endereço logico " + enderecoLogico);
        TP tp = (TP) model.getMemoriaPrincipal().getProcessos_TP().get(nomeProc); //retorna a TP associada àquele processo

        Processo processo = null;
        int indexP = 0;
        for (int i = 0; i < processos.size(); i++) {
            if (processos.get(i).getNome().equals(nomeProc)) {
                processo = processos.get(i);
                indexP = i;
            }
        }
        int indexTP = CelulaTP.numPg(enderecoLogico, TP.qtdIDPg(indexP));

        System.out.println(indexTP);

        if (tp != null) {
            if (model.getMemoriaPrincipal().isCheia()) {
                JOptionPane.showMessageDialog(view, "Memoria principal cheia! \n Falta de paginas!");
                JOptionPane.showMessageDialog(view, "Executar politica de substituicao " + this.model.getPolitica() + " com escopo " + this.model.getEscopo());
                if (this.model.getPolitica().equalsIgnoreCase("FIFO")) {
                    PoliticaDeSubstituicao p = new FIFO();
                    if (this.model.getEscopo().equals("LOCAL")) {
//                    executa(Pagina pagina, MemoriaVirtual mv, ArrayList<Processo> processos, boolean ehEscopoLocal, int momentoAtual, char tipoInstrucao);
                        p.executa(processo.getPaginas()[indexTP], model, processos, true, momentoAtual, tipoInstrucao);
                    } else {
                        p.executa(processo.getPaginas()[indexTP], model, processos, false, momentoAtual, tipoInstrucao);
                    }

                }
                if (this.model.getPolitica().equalsIgnoreCase("LRU")) {
                    PoliticaDeSubstituicao p = new LRU();
                    if (this.model.getEscopo().equals("LOCAL")) {
//                    executa(Pagina pagina, MemoriaVirtual mv, ArrayList<Processo> processos, boolean ehEscopoLocal, int momentoAtual, char tipoInstrucao)
                        p.executa(processo.getPaginas()[indexTP], model, processos, true, momentoAtual, tipoInstrucao);
                    } else {
                        p.executa(processo.getPaginas()[indexTP], model, processos, false, momentoAtual, tipoInstrucao);
                    }
                }
                momentoAtual++;

            } else {
                if (tipoInstrucao == 'R') {
                    if (tp.getCelulas()[indexTP].isP()) {
                        System.out.println(model.getMemoriaSecundaria().getQuadro(tp.getCelulas()[indexTP].getNumQuadro()).getPagina().getNomeProc());
                    } else {
                        int i = 0;

                        while (!this.model.getMemoriaPrincipal().getQuadro(i).isVazio() && (i < this.model.getMemoriaPrincipal().getQtdQuadros())) {
                            System.out.println("opa!");
                            i++;
                        }
                        this.model.getMemoriaPrincipal().setQuadro(model.getMemoriaSecundaria().getQuadro(tp.getCelulas()[indexTP].getNumQuadro()), i);
                        tp.getCelulas()[indexTP].setP();
                        this.carregaMP();
                        if (tipoInstrucao == 'W') {
                            tp.getCelulas()[indexTP].setM();
                            this.carregaMP();
                            this.carregaMS();
                        }
                        momentoAtual++;
                    }
                }
            }
        } else {
            JOptionPane.showMessageDialog(view, "Processo " + nomeProc + " não existe!");
        }

        JOptionPane.showMessageDialog(view, "Executou a instrução");
    }

    public void executaInstrucao2(String nomeProc, char tipoInstrucao, String enderecoLogico, ArrayList<Processo> processos) {
        TP tp = (TP) model.getMemoriaPrincipal().getProcessos_TP().get(nomeProc); //retorna a TP associada àquele processo

        Processo processo = null;
        int indexP = 0;
        for (int i = 0; i < processos.size(); i++) {
            if (processos.get(i).getNome().equals(nomeProc)) {
                processo = processos.get(i);
                indexP = i;
                i = processos.size();
            }
        }
        int indexTP = CelulaTP.numPg(enderecoLogico, TP.qtdIDPg(indexP));
        //TEM QUE CRIAR A TP ANTES
        if (processo != null) {
            if (model.getMemoriaPrincipal().isCheia()) {
                JOptionPane.showMessageDialog(view, "Memoria principal cheia! \n Falta de paginas!");
                JOptionPane.showMessageDialog(view, "Executar politica de substituicao " + this.model.getPolitica() + " com escopo " + this.model.getEscopo());
                if (this.model.getPolitica().equalsIgnoreCase("FIFO")) {
                    PoliticaDeSubstituicao p = new FIFO();
                    if (this.model.getEscopo().equals("LOCAL")) {
                        p.executa(processo.getPaginas()[indexTP], model, processos, true, momentoAtual, tipoInstrucao);
                    } else {
                        p.executa(processo.getPaginas()[indexTP], model, processos, false, momentoAtual, tipoInstrucao);
                    }
                }
                if (this.model.getPolitica().equalsIgnoreCase("LRU")) {
                    PoliticaDeSubstituicao p = new LRU();
                    if (this.model.getEscopo().equals("LOCAL")) {
                        p.executa(processo.getPaginas()[indexTP], model, processos, true, momentoAtual, tipoInstrucao);
                    } else {
                        p.executa(processo.getPaginas()[indexTP], model, processos, false, momentoAtual, tipoInstrucao);
                    }
                }
                momentoAtual++;
            } else {
                boolean sucesso = false;
                if (!isTPCarregada(nomeProc)) {
                   tp = this.model.getMemoriaPrincipal().criarTP(processo, indexTP, this.model.getMemoriaSecundaria());
                }
                if (isTPCarregada(nomeProc)) {
                    if (tipoInstrucao == 'R') {
                        if (tp.getCelulas()[indexTP].isP()) {
                            System.out.println(model.getMemoriaSecundaria().getQuadro(tp.getCelulas()[indexTP].getNumQuadro()).getPagina().getNomeProc());
                        } else {
                            int i = 0;
                            while (!this.model.getMemoriaPrincipal().getQuadro(i).isVazio()) {
                                i++;
                            }
                            this.model.getMemoriaPrincipal().setQuadro(model.getMemoriaSecundaria().getQuadro(tp.getCelulas()[indexTP].getNumQuadro()), i);
                            tp.getCelulas()[indexTP].setP();
                            this.carregaMP();
                        }
                        if (tipoInstrucao == 'W') {
                            tp.getCelulas()[indexTP].setM();
                            this.carregaMP();
                            this.carregaMS();
                        }
                        momentoAtual++;
                    }
                    JOptionPane.showMessageDialog(view, "Instrução executada!");
                } else {
                    JOptionPane.showMessageDialog(view, " A TP do processo não pôde ser criada e a instrução não foi executada");
                }
            }
        } else {
            JOptionPane.showMessageDialog(view, "Processo " + nomeProc + " não existe e instrução não foi executada!");
        }
    }
}
